Skip to content

Enable autovectorization on all compilers#3739

Open
ann0see wants to merge 1 commit into
jamulussoftware:mainfrom
ann0see:autovectorize
Open

Enable autovectorization on all compilers#3739
ann0see wants to merge 1 commit into
jamulussoftware:mainfrom
ann0see:autovectorize

Conversation

@ann0see

@ann0see ann0see commented Jun 16, 2026

Copy link
Copy Markdown
Member

Short description of changes

Enables autovectorization throughout the whole codebase. We found out that there is no vectorization especially of the server side mixing code (#3662 (comment))
I consider this safe to default enable; in case of bugs we'd have a compiler bug.

CHANGELOG: Performance: Enable auto vectorization by default

Context: Fixes an issue?

Related to: #3662 (comment)

Does this change need documentation? What needs to be documented and how?

Status of this Pull Request

Ready for testing on all supported OS.

What is missing until this pull request can be merged?

Build with multiple compilers

Checklist

  • I've verified that this Pull Request follows the general code principles
  • I tested my code and it does what I want
  • My code follows the style guide
  • I waited some time after this Pull Request was opened and all GitHub checks completed without errors.
  • I've filled all the content above

AUTOBUILD: Please build all targets

@dingodoppelt

Copy link
Copy Markdown
Member

As mentioned in #3662 my compiler seems to autovectorize already. I see -O2 is set when I compile. -O3 includes -ftree-vectorize. Have you looked into setting -O3 as an alternative as well?
How can we autobuild with debug symbols? It would be interesting to know if some runners already automagically handle things like my compiler does.

@mcfnord

mcfnord commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

I benchmarked this change on Linux to help move it forward. Summary: the claim in the PR description is correct — with the current -O2 build flags, g++ vectorizes none of the mixing loops in CServer::MixEncodeTransmitData, and this one-line flag fixes that, making the mix loops 2.2–3.8× faster. It also answers @dingodoppelt's -O3 question: -O3 produces essentially identical mixing performance, so -ftree-vectorize alone gets all of the benefit with a much smaller change.

Setup: g++ 13.3.0 (Ubuntu 24.04, x86-64), current main (6b7a0ad), compiled with the exact flags qmake generates (-pipe -O2 -std=gnu++11 -fPIC + project defines/includes), comparing three variants: stock -O2, -O2 -ftree-vectorize (this PR), and -O3.

1. Compiler vectorization reports on the real server.cpp

-fopt-info-vec-optimized, filtered to MixEncodeTransmitData:

Variant Vectorized loops in the mix function
-O2 (current) 0 (only one trivial SLP basic-block)
-O2 -ftree-vectorize (this PR) 8 — all four mono-target mix loops, both stereo-target no-delay-pan mix loops, both Float2Short conversion loops
-O3 same 8 loops

So on GCC 13 nothing in the mixing path vectorizes today, and the PR's flag reaches exactly the same set of loops as -O3. (The delay-pan loops don't vectorize under any variant due to the wrap-around conditionals — pre-existing, unchanged.)

2. Microbenchmark of the mixing loops

Loop bodies lifted verbatim from MixEncodeTransmitData (CVector is std::vector, runtime trip count, same access pattern). Each measurement is one full target-channel frame: buffer reset + mix of N clients + Float2Short conversion; best of 30 runs × 20 000 reps. Times in ns per target-channel frame:

Frame Clients Mode -O2 -O2 -ftree-vectorize -O3 Speedup (PR vs -O2)
64 10 mono 1091 285 260 3.8×
64 10 stereo 1024 407 418 2.5×
64 50 mono 3235 1104 978 2.9×
64 50 stereo 4931 1986 1822 2.5×
128 10 mono 1339 419 551 3.2×
128 10 stereo 2642 1177 1183 2.2×
128 50 mono 7873 2463 2659 3.2×
128 50 stereo 14248 5232 5130 2.7×

Whole-server impact scales with N² (each of N clients gets its own N-way mix). Example: 50 mono clients at the 128-sample frame size = 50 × 7.9 µs = ~394 µs of mixing per 2.67 ms frame period (≈15% of a core) at -O2, dropping to ~123 µs (≈4.6%) with this PR. Stereo: ≈27% → ≈10%.

3. Safety notes

  • These loops vectorize over the sample index; each output sample keeps its exact scalar operation order (no FP reassociation — -ftree-vectorize does not imply -ffast-math), so output is bit-identical, consistent with the "safe to default-enable" assessment.
  • The full autobuild matrix on this PR is green, including both Windows builds — MSVC ignores the unknown -ftree-vectorize with a warning, so the flag is inert (not harmful) there. If the warning noise bothers anyone it could be scoped to gcc/clang mkspecs, but it's not a correctness issue.
  • @dingodoppelt: on g++ 13, plain -O2 definitely does not enable loop vectorization (-ftree-vectorize is only implied from -O3 up) — if your local builds vectorize at -O2, something else in your flags is adding it. And per the table above, -O3 buys nothing further for this code, so the PR's minimal flag seems like the right call.

Benchmark source available on request.

🤖 Generated with Claude Code

@pljones

pljones commented Jul 19, 2026

Copy link
Copy Markdown
Collaborator

MSVC ignores the unknown -ftree-vectorize with a warning

I think it would be worth putting a guard in the Jamulus.pro, in that case, with a comment saying it's only in GCC.

Additionally, it might be worth investigating what the equivalent in the MSVC builds looks like - in terms of performance now and potential for optimisation. This step isn't a blocker, though.

@pljones pljones added this to Tracking Jul 19, 2026
@github-project-automation github-project-automation Bot moved this to Triage in Tracking Jul 19, 2026
@pljones pljones added this to the Release 4.0.0 milestone Jul 19, 2026
@pljones

pljones commented Jul 19, 2026

Copy link
Copy Markdown
Collaborator

I've added this to 4.0.0 as it's a small change with potentially wide-scale benefit right now.

@pljones pljones moved this from Triage to In Progress in Tracking Jul 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: In Progress

Development

Successfully merging this pull request may close these issues.

4 participants